package pl.pasu.mydiet.server;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Session;

import pl.pasu.mydiet.client.DietService;
import pl.pasu.mydiet.client.dto.ConstProductDTO;
import pl.pasu.mydiet.client.dto.DietPlanDTO;
import pl.pasu.mydiet.client.dto.DietProductDTO;
import pl.pasu.mydiet.client.dto.DietUserDTO;
import pl.pasu.mydiet.domain.ConstProduct;
import pl.pasu.mydiet.domain.DietPlan;
import pl.pasu.mydiet.domain.DietProduct;
import pl.pasu.mydiet.domain.DietUser;
import pl.pasu.mydiet.shared.DietResponse;
import pl.pasu.mydiet.shared.DietResponse.Code;
import pl.pasu.mydiet.util.HibernateUtil;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class DietServiceImpl extends RemoteServiceServlet implements
		DietService {

	@Override
	public DietResponse createUser(DietUserDTO userDTO) {
		DietUser user = new DietUser(userDTO);
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		List<DietUser> accounts = new ArrayList<DietUser>(session.createQuery(
				"from DietUser").list());
		for (Iterator<DietUser> iterator = accounts.iterator(); iterator
				.hasNext();) {
			DietUser dietUser = iterator.next();
			if (user.getDisplayName().equalsIgnoreCase(
					dietUser.getDisplayName())) {
				session.getTransaction().commit();
				return new DietResponse(Code.FAIL, "User already exists.");

			}
		}
		session.save(user);
		session.getTransaction().commit();
		return new DietResponse(Code.OK, "Done creating user.");
	}

	@Override
	public List<DietUserDTO> getUsers() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		List<DietUser> accounts = new ArrayList<DietUser>(session.createQuery(
				"from DietUser").list());
		List<DietUserDTO> accountDTOs = new ArrayList<DietUserDTO>(
				accounts != null ? accounts.size() : 0);
		if (accounts != null) {
			for (DietUser account : accounts) {
				accountDTOs.add(createUserDTO(account));
			}
		}
		session.getTransaction().commit();
		return accountDTOs;
	}

	private DietUserDTO createUserDTO(DietUser u) {
		List<DietPlan> records = u.getPlans();
		List<DietPlanDTO> recordDTOs = new ArrayList<DietPlanDTO>(
				records != null ? records.size() : 0);
		if (records != null) {
			for (DietPlan record : records) {
				recordDTOs.add(createDietPlanDTO(record));
			}
		}
		return new DietUserDTO(u.getId(), u.getDisplayName(), u.getPassword(),
				u.getCreated(), recordDTOs);
	}

	private DietPlanDTO createDietPlanDTO(DietPlan pl) {
		List<DietProduct> records = pl.getProducts();
		List<DietProductDTO> recordDTOs = new ArrayList<DietProductDTO>(
				records != null ? records.size() : 0);
		if (records != null) {
			for (DietProduct record : records) {
				recordDTOs.add(createDietProductDTO(record));
			}
		}
		return new DietPlanDTO(pl.getId(), pl.getName(), pl.getCreated(),
				pl.getCorrespondingDay(), recordDTOs);
	}

	private DietProductDTO createDietProductDTO(DietProduct pr) {
		return new DietProductDTO(pr.getId(), pr.getName(), pr.getAmount(),
				pr.getType(), pr.getDayTime(), pr.getDescription(),
				pr.getAdditionalUserComment());
	}

	private ConstProductDTO createConstProductDTO(ConstProduct p) {
		return new ConstProductDTO(p.getId(), p.getName(), p.getType(),
				p.getSubtype(), p.getGroup(), p.getDescription());
	}

	@Override
	public List<ConstProductDTO> getAvailableProducts() {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		List<ConstProduct> prods = new ArrayList<ConstProduct>(session
				.createQuery("from ConstProduct").list());
		List<ConstProductDTO> prodDTOs = new ArrayList<ConstProductDTO>(
				prods != null ? prods.size() : 0);
		if (prods != null) {
			for (ConstProduct pr : prods) {
				prodDTOs.add(createConstProductDTO(pr));
			}
		}
		session.getTransaction().commit();
		return prodDTOs;
	}

}
